//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Controls;
using OpenLS.Chart.Internals;
using OpenLS.Core.Serialization;
using System.Windows.Markup;

namespace OpenLS.Chart
{
    [ContentProperty("Series")]
    public abstract class BarChartBase : ChartBase, IDataLabelsOwner
    {
        private const BarGrouping defaultGrouping = BarGrouping.Standard;
        private BarGrouping _grouping;
        private ObservableCollection<BarSeries> _series;
        private BarDirection direction;
        private DataLabels dLbls;

        private bool varyColors;

        public bool VaryColors
        {
            get { return varyColors; }
            set
            {
                varyColors = value;
                notifyPropertyChanged("VaryColors");
            }
        }

        public DataSource Categories
        {
            get
            {
                if (Series.Count == 0)
                    return null;
                BarSeries firstSeries = Series[0];
                DataSource ds = firstSeries.Categories;
                if (ds == null)
                {
                    int count = GetDisplayInformation().Count;
                    return StringLiteral.NewStringLiteral(1, count);
                }
                return ds;
            }
        }


        public DataLabels DataLabels
        {
            get { return dLbls; }
            set { dLbls = value;notifyPropertyChanged("DataLabels"); }
        }

        public ObservableCollection<BarSeries> Series
        {
            get
            {
                if (_series == null)
                {
                    _series = CreateSeriesCollection<BarSeries>();
                    _series.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs args)
                                                     {
                                                         if (args.NewItems != null)
                                                             foreach (BarSeries series in args.NewItems)
                                                                 series.ValueChanged += OnSeriesChanged;
                                                         if (args.OldItems != null)
                                                             foreach (BarSeries series in args.OldItems)
                                                                 series.ValueChanged -= OnSeriesChanged;
                                                     };
                }
                return _series;
            }
        }

        public BarGrouping Grouping
        {
            get { return _grouping; }
            set { _grouping = value;notifyPropertyChanged("Grouping"); }
        }

        public BarDirection Direction
        {
            get { return direction; }
            set { direction = value; notifyPropertyChanged("Direction");
                OnDirectionChanged(value); }
        }

        internal virtual void OnDirectionChanged(BarDirection direction)
        {
        }

        public Orientation PrimaryOrientation
        {
            get
            {
                if (Direction == BarDirection.Column)
                    return Orientation.Horizontal;
                return Orientation.Vertical;
            }
        }

        public Orientation SecondaryOrientation
        {
            get
            {
                if (Direction == BarDirection.Column)
                    return Orientation.Vertical;
                return Orientation.Horizontal;
            }
        }

        #region IChartWithDisplayInformation Members

        #endregion

        internal void ReadXmlBase(ReadContext c)
        {
            Direction = c.ReadElementEnumAttribute<BarDirection>("barDir", "val");
            Grouping =
                c.ReadOptionalElementEnumAttribute("grouping", "val", defaultGrouping, defaultGrouping);
            varyColors = ChartHelper.ReadVaryColors(c);
            while (c.ReaderLocalName == "ser")
            {
                var s = new BarSeries();
                s.ReadXmlCore(c);
                Series.Add(s);
            }
            DataLabels = c.ReadOptionalElement<DataLabels>(DataLabels.xmlName);
        }

        internal void WriteXmlBase(WriteContext context)
        {
            context.WriteElementEnumAttribute("barDir", Direction);
            context.WriteOptionalElementEnumAttribute("grouping", Grouping, defaultGrouping,
                                                                   defaultGrouping);
            ChartHelper.WriteVaryColors(context, VaryColors);
            foreach (BarSeries s in Series)
                s.WriteXmlCore(context);
            context.WriteOptionalElement(DataLabels);
        }

        private void OnSeriesChanged(object sender, EventArgs args)
        {
            notifyPropertyChanged("Categories");
        }


        internal INumericChartDisplayInformation GetDisplayInformation()
        {
            switch (Grouping)
            {
                case BarGrouping.Standard:
                case BarGrouping.Clustered:
                    return new ClusteredDisplayInformation(Series);
                case BarGrouping.Stacked:
                    return new StackedDisplayInformation(Series);
                case BarGrouping.PercentStacked:
                    return new PercentStackedDisplayInformation(Series);
                default:
                    throw new NotSupportedException();
            }
        }

        internal void InvalidateCategories()
        {
            notifyPropertyChanged("Categories");
        }
    }
}